/*!
 * \file StdUtils.hpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief C++标准库的一些常用功能的简单封装工具集
 * 
 * \details 提供C++标准库中常用功能的简化封装，包括：
 *          - 线程相关：线程类型定义和管理
 *          - 锁机制：互斥锁、递归锁、条件变量等同步原语
 *          - 文件操作：文件读写、存在性检查等基础文件操作
 *          - 智能指针：线程智能指针封装
 *          
 *          该工具集旨在简化常用C++标准库功能的使用，提供统一的接口风格，
 *          降低开发复杂度，提高代码可读性和维护性。
 */
#pragma once

#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <stdint.h>
#include <string>

#if _MSC_VER
#include <io.h>
#else
#include <unistd.h>
#endif

//////////////////////////////////////////////////////////////////////////
/*! 
 * \brief 标准线程类型定义
 * 
 * \details 对std::thread的类型别名定义，提供统一的线程类型名称
 */
typedef std::thread StdThread;

/*! 
 * \brief 标准线程智能指针类型定义
 * 
 * \details 基于std::shared_ptr的线程智能指针，支持线程对象的自动内存管理
 */
typedef std::shared_ptr<StdThread> StdThreadPtr;

//////////////////////////////////////////////////////////////////////////
/*! 
 * \brief 标准递归互斥锁类型定义
 * 
 * \details 对std::recursive_mutex的类型别名，支持同一线程的重复加锁
 */
typedef std::recursive_mutex	StdRecurMutex;

/*! 
 * \brief 标准独占互斥锁类型定义
 * 
 * \details 对std::mutex的类型别名，提供基础的互斥访问控制
 */
typedef std::mutex				StdUniqueMutex;

/*! 
 * \brief 标准条件变量类型定义
 * 
 * \details 对std::condition_variable_any的类型别名，支持线程间的条件等待和通知
 */
typedef std::condition_variable_any	StdCondVariable;

/*! 
 * \brief 标准独占锁类型定义
 * 
 * \details 对std::unique_lock的类型别名，提供RAII风格的锁管理
 */
typedef std::unique_lock<StdUniqueMutex>	StdUniqueLock;

/*!
 * \brief 通用锁管理器模板类
 * 
 * \details RAII风格的锁管理器，支持任意类型的锁对象。
 *          构造时自动加锁，析构时自动解锁，确保异常安全。
 *          
 * \tparam T 锁类型，必须支持lock()和unlock()方法
 * 
 * \usage
 * \code
 * StdUniqueMutex mtx;
 * {
 *     StdLocker<StdUniqueMutex> locker(mtx);
 *     // 临界区代码...
 * } // 自动解锁
 * \endcode
 */
template<typename T>
class StdLocker
{
public:
	/*!
	 * \brief 构造函数，自动加锁
	 * \param mtx 要管理的锁对象引用
	 * 
	 * \details 构造时立即对传入的锁对象进行加锁操作
	 */
	StdLocker(T& mtx)
	{
		mtx.lock();
		_mtx = &mtx;
	}

	/*!
	 * \brief 析构函数，自动解锁
	 * 
	 * \details 析构时自动对锁对象进行解锁操作，确保RAII语义
	 */
	~StdLocker(){
		_mtx->unlock();
	}

private:
	T* _mtx;	///< 锁对象指针
};

//////////////////////////////////////////////////////////////////////////
/*!
 * \brief 标准文件操作工具类
 * 
 * \details 提供常用文件操作的静态方法集合，包括：
 *          - 文件内容读取：支持二进制和文本文件读取
 *          - 文件内容写入：支持字符串和二进制数据写入
 *          - 文件存在性检查：跨平台的文件存在性判断
 *          
 *          所有方法都是静态方法，无需实例化即可使用。
 *          提供简洁的文件操作接口，屏蔽平台差异。
 */
class StdFile
{
public:
	/*!
	 * \brief 读取文件全部内容到字符串
	 * \param filename 文件路径
	 * \param content 输出参数，存储文件内容的字符串
	 * \return 读取的字节数
	 * 
	 * \details 以二进制模式打开文件，读取全部内容到字符串中。
	 *          自动获取文件大小并分配相应的内存空间。
	 *          适用于读取配置文件、文本文件等较小的文件。
	 */
	static inline uint64_t read_file_content(const char* filename, std::string& content)
	{
		FILE* f = fopen(filename, "rb");
		fseek(f, 0, SEEK_END);
		uint32_t length = ftell(f);
		content.resize(length);   // allocate memory for a buffer of appropriate dimension
		fseek(f, 0, 0);
		size_t bytes_read = fread((void*)content.data(), sizeof(char), length, f);
		(void)bytes_read; // 避免未使用变量警告
		fclose(f);
		return length;
	}

	/*!
	 * \brief 将字符串内容写入文件
	 * \param filename 文件路径
	 * \param content 要写入的字符串内容
	 * 
	 * \details 以二进制模式创建/覆盖文件，将字符串内容写入。
	 *          如果文件已存在则覆盖，不存在则创建。
	 */
	static inline void write_file_content(const char* filename, const std::string& content)
	{
		FILE* f = fopen(filename, "wb");
		fwrite((void*)content.data(), sizeof(char), content.size(), f);
		fclose(f);
	}

	/*!
	 * \brief 将二进制数据写入文件
	 * \param filename 文件路径
	 * \param data 要写入的二进制数据指针
	 * \param length 数据长度（字节数）
	 * 
	 * \details 以二进制模式创建/覆盖文件，将指定长度的数据写入。
	 *          适用于写入任意类型的二进制数据。
	 */
	static inline void write_file_content(const char* filename, const void* data, std::size_t length)
	{
		FILE* f = fopen(filename, "wb");
		fwrite(data, sizeof(char), length, f);
		fclose(f);
	}

	/*!
	 * \brief 检查文件是否存在
	 * \param filename 文件路径
	 * \return true表示文件存在，false表示文件不存在
	 * 
	 * \details 跨平台的文件存在性检查，在Windows下使用_access，
	 *          在其他平台使用access系统调用。
	 */
	static inline bool exists(const char* filename)
	{
#if _WIN32
		int ret = _access(filename, 0);
#else
		int ret = access(filename, 0);
#endif
		return ret == 0;
	}
};
